package com.qdev.apps.core.aop.interceptor;

import java.io.Serializable;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Quake Wang
 * @since 2004-10-22
 * @version $Revision: 1.1 $
 */
public class CacheInterceptor implements MethodInterceptor {
    private static final Log log = LogFactory.getLog(CacheInterceptor.class);
    private static final String CACHE_NAME = "com.qdev.apps.core.aop.interceptor.CacheInterceptor";
    private Cache cache;

    public CacheInterceptor() throws CacheException {
        CacheManager manager = CacheManager.getInstance();
        cache = manager.getCache(CACHE_NAME);
        if (cache == null) {
            log.warn("Could not find configuration for " + CACHE_NAME + ". Configuring using the defaultCache settings.");
            manager.addCache(CACHE_NAME);
            cache = manager.getCache(CACHE_NAME);
        }
    }

    public Object invoke(MethodInvocation invocation) throws Throwable {
        final Long key = new Long(calculateHash(invocation));
        Element element = cache.get(key);

        if (element == null) {
            element = new Element(key, (Serializable) invocation.proceed());
            cache.put(element);
        }

        return element.getValue();
    }

    private long calculateHash(MethodInvocation invocation) {
        int result = 17;
        result = 37 * result + invocation.getMethod().getName().hashCode();
        Object[] arguments = invocation.getArguments();
        if (arguments != null) {
            for (int i = 0, j = arguments.length; i < j; i++) {
                result = 37 * result + arguments[i].hashCode();
            }
        }
        return result;
    }

}